﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Tensop.Net.Tcp.Protocol
{
    public sealed class ProtocolCatcher
    {
        static Dictionary<int,IProtocolService>              _directMapping;
        static Dictionary<string,int>                   _nameMapping;
        static Dictionary<int,string>                   _roleMapping;

        static ProtocolCatcher()
        {
            _directMapping = new Dictionary<int, IProtocolService>( 32 );
            _nameMapping = new Dictionary<string, int>( 32 );
            _roleMapping = new Dictionary<int, string>();
        }

        public IProtocolService Registry(IProtocolService handler, string name)
        {
            var key = handler.GetKeys();
            _directMapping.Add( key, handler );
            _nameMapping.Add( name, key );
            _roleMapping.Add( key, name );
            return handler;
        }

        public void UnRegistry(IProtocolService handler)
        {
            var key = handler.GetKeys();
            _directMapping.Remove( key );
            var name = _roleMapping[key];
            _roleMapping.Remove( key );
            _nameMapping.Remove( name );
        }

        internal ArraySegment<byte> Routed(ArraySegment<byte> data, Client c, byte protocol, byte version)
        {
            var key = MappingKey( protocol, version );
            try
            {
                var parser = _directMapping[key];
                return parser.Parse( data, c );
            } catch
            {
                return data;
            }
        }

        static public short MappingKey(byte protocol, byte version) => (short) ( ( protocol << 8 ) | version );

        /// <summary>
        /// 从协议捕获器中注册或取消注册一条协议解析服务,get访问器用于注册，set访问器用于取消注册
        /// </summary>
        /// <param name="trigger">将要添加的服务</param>
        /// <param name="name">对应的命名</param>
        /// <returns></returns>
        public IProtocolService this[IProtocolService trigger, string name] {
            get => Registry( trigger, name );
            set => UnRegistry( value );
        }

        /// <summary>
        /// 使用服务命名，获得一条服务规则（如果不存在则返回空置）
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public IProtocolService this[string name] {
            get {
                try {return _directMapping[_nameMapping[name]]; } catch { return null; }
            }
        }
    }
}
